#include "stdint.h"
#include "pin.h"
#include "ptdef.h"
#include "device.h"
#include "ptdebug.h"

static struct pt_device_pin _hw_pin;


static int32_t  _pin_control ( pt_device_t dev, int cmd, void * args )
{
	struct pt_device_pin_mode * mode;
	struct pt_device_pin * pin = ( struct pt_device_pin * ) dev;

	mode = ( struct pt_device_pin_mode * ) args;

	if ( mode == PT_NULL ) {
		return -PT_ERROR;
	}

	pin->ops->pin_mode ( dev, ( int32_t ) mode->pin, ( int32_t ) mode->mode );

	return 0;
}

static uint32_t _pin_read ( pt_device_t dev, int32_t pos, void * buffer, uint32_t size )
{
	struct pt_device_pin_status * status;
	struct pt_device_pin * pin = ( struct pt_device_pin * ) dev;

	status = ( struct pt_device_pin_status * ) buffer;

	if ( status == PT_NULL || size != sizeof ( *status ) ) {
		return 0;
	}

	status->status = pin->ops->pin_read ( dev, status->pin );
	return size;
}

static uint32_t _pin_write ( pt_device_t dev, int32_t pos, const void * buffer, uint32_t size )
{
	struct pt_device_pin_status * status;
	struct pt_device_pin * pin = ( struct pt_device_pin * ) dev;

	status = ( struct pt_device_pin_status * ) buffer;

	if ( status == PT_NULL || size != sizeof ( *status ) ) {
		return 0;
	}

	pin->ops->pin_write ( dev, ( int32_t ) status->pin, ( int32_t ) status->status );

	return size;
}


int pt_device_pin_register ( uint8_t device_id, const struct pt_pin_ops * ops, void * user_data )
{
	_hw_pin.parent.type         = PT_Device_Class_Miscellaneous;
	_hw_pin.parent.rx_indicate  = PT_NULL;
	_hw_pin.parent.tx_complete  = PT_NULL;


	_hw_pin.parent.init         = PT_NULL;
	_hw_pin.parent.open         = PT_NULL;
	_hw_pin.parent.close        = PT_NULL;
	_hw_pin.parent.read         = _pin_read;
	_hw_pin.parent.write        = _pin_write;
	_hw_pin.parent.control      = _pin_control;


	_hw_pin.ops                 = ops;
	_hw_pin.parent.user_data    = user_data;

	/* register a character device */
	//不用name, 用device_id
	pt_device_register ( &_hw_pin.parent, device_id, PT_DEVICE_FLAG_RDWR );

	return 0;
}

int32_t pt_pin_attach_irq ( int32_t pin, uint32_t mode,
							void ( *hdr ) ( void * args ), void * args )
{
	if ( _hw_pin.ops->pin_attach_irq ) {
		return _hw_pin.ops->pin_attach_irq ( &_hw_pin.parent, pin, mode, hdr, args );
	}

	return PT_ENOSYS;
}

int32_t pt_pin_detach_irq ( int32_t pin )
{
	if ( _hw_pin.ops->pin_detach_irq ) {
		return _hw_pin.ops->pin_detach_irq ( &_hw_pin.parent, pin );
	}

	return PT_ENOSYS;
}

int32_t pt_pin_irq_enable ( int32_t pin, uint32_t enabled )
{
	if ( _hw_pin.ops->pin_irq_enable ) {
		return _hw_pin.ops->pin_irq_enable ( &_hw_pin.parent, pin, enabled );
	}

	return PT_ENOSYS;
}

void pt_pin_mode ( int32_t pin, int32_t mode )
{
	PT_ASSERT ( mode >= PIN_MODE_OUTPUT && mode <= PIN_MODE_OUTPUT_OD );
	PT_ASSERT ( _hw_pin.ops->pin_mode != PT_NULL );
	_hw_pin.ops->pin_mode ( &_hw_pin.parent, pin, mode );
}

int pt_pin_read ( int32_t pin )
{
    PT_ASSERT ( _hw_pin.ops->pin_read != PT_NULL );
	return _hw_pin.ops->pin_read ( &_hw_pin.parent, pin );
}

void pt_pin_write ( int32_t pin, int32_t value )
{
    PT_ASSERT ( _hw_pin.ops->pin_write != PT_NULL );
	_hw_pin.ops->pin_write ( &_hw_pin.parent, pin, value );
}

